<template>
  <!-- 保持模板不变 -->
  <div class="chart-container">
    <div class="control-panel">
      <div class="time-control">
        <button @click="playPause">{{ isPlaying ? '暂停' : '播放' }}</button>
        <input type="range" v-model="currentIndex" min="0" :max="mockData.length - 1">
      </div>
      <div class="legend">
        <div v-for="(item, index) in legendData" :key="index" class="legend-item">
          <span class="dot" :style="{ backgroundColor: item.color }"></span>
          {{ item.name }}
        </div>
      </div>
    </div>
    <div class="right-controls">
      <button @click="showInputForm = true" class="input-form-button">
        填写数据
      </button>
      <button @click="toggleRoam" class="roam-control-button">
        {{ isRoamEnabled ? '禁止缩放移动' : '开启缩放移动' }}
      </button>
    </div>
    <div ref="chartRef" class="chart"></div>

    <div class="data-panel">
      <h3 class="panel-title">预测详情</h3>
      <div class="panel-content">
        <div class="data-item">
          <label>当前时间：</label>
          <span>{{ currentTime }}</span>
        </div>
        <div class="data-item">
          <label>预测概率：</label>
          <span>{{ currentProbability }}%</span>
        </div>
        <div class="data-item">
          <label>覆盖半径：</label>
          <span>{{ currentRadius }}公里</span>
        </div>
        <div class="data-item">
          <label>预测可信度：</label>
          <span>{{ confidenceLevel }}</span>
        </div>
      </div>
    </div>

    <!-- 输入表单弹窗 -->
    <div v-if="showInputForm" class="input-form-overlay">
      <div class="input-form">
        <h3>输入预测参数</h3>
        <div class="form-group">
          <label>起始纬度：</label>
          <input type="number" v-model="formData.start_lat" step="0.000001">
        </div>
        <div class="form-group">
          <label>起始经度：</label>
          <input type="number" v-model="formData.start_lon" step="0.000001">
        </div>
        <div class="form-group">
          <label>年龄：</label>
          <input type="number" v-model="formData.age">
        </div>
        <div class="form-group">
          <label>性别：</label>
          <select v-model="formData.gender">
            <option value="male">男</option>
            <option value="female">女</option>
          </select>
        </div>
        <div class="form-group">
          <label>身高(cm)：</label>
          <input type="number" v-model="formData.height">
        </div>
        <div class="form-group">
          <label>体重(kg)：</label>
          <input type="number" v-model="formData.weight">
        </div>
        <div class="form-group">
          <label>交通方式：</label>
          <select v-model="formData.transport_mode">
            <option value="walk">步行</option>
            <option value="bike">自行车</option>
            <option value="car">汽车</option>
          </select>
        </div>
        <div class="form-buttons">
          <button @click="submitForm" class="submit-button">提交</button>
          <button @click="showInputForm = false" class="cancel-button">取消</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
import * as echarts from 'echarts/core'
import { ScatterChart, LinesChart, MapChart } from 'echarts/charts'
import { TooltipComponent, VisualMapComponent, TimelineComponent, GeoComponent } from 'echarts/components'
import type { ECharts, ComposeOption } from 'echarts/core'
import type { TimelineComponentOption } from 'echarts/components'
import type { ScatterSeriesOption, LinesSeriesOption } from 'echarts/charts'
import type { GeoComponentOption } from 'echarts/components'
import chinaJson from '@/assets/china.json' // 确保正确引入中国地图数据
import trajectoryRequest from '@/utils/trajectoryRequest' // 使用新的请求实例

// 注册必需组件
echarts.use([
  ScatterChart,
  LinesChart,
  MapChart,
  TooltipComponent,
  VisualMapComponent,
  TimelineComponent,
  GeoComponent
])

// 注册中国地图
echarts.registerMap('china', chinaJson as any)

interface PredictPoint {
  name: string
  value: [number, number, number]
  time: string
  radius: number
  confidence: number
}

interface Prediction {
  date: string
  mean_coordinates: [number, number]
  std_deviation: [number, number]
  search_radius_km: number
  probability: number
}

interface ApiResponse {
  predictions: Prediction[]
}

const chartRef = ref<HTMLElement | null>(null)
const currentIndex = ref(0)
const isPlaying = ref(false)
const isRoamEnabled = ref(false)
let chartInstance: ECharts | null = null
let intervalId: number | null = null

const colorPalette = {
  mainRed: '#ff4d4d',
  secondaryRed: '#ff9999',
  textPrimary: '#ff9999',
}

const legendData = [
  { name: '失踪起点', color: colorPalette.mainRed },
  { name: '预测轨迹', color: colorPalette.secondaryRed },
  { name: '高概率区域', color: 'rgba(255,77,77,0.3)' }
]

// 添加表单相关的状态
const showInputForm = ref(false)
const formData = ref({
  start_lat: 39.33,
  start_lon: 112.43,
  age: 8,
  gender: 'male',
  height: 123,
  weight: 35,
  transport_mode: 'walk'
})

// 修改 mockData 的定义，使其可以被更新
const mockData = ref<PredictPoint[]>([])

// 修改计算属性，添加空值检查
const currentTime = computed(() => mockData.value[currentIndex.value]?.time || '')
const currentProbability = computed(() => mockData.value[currentIndex.value] ? (mockData.value[currentIndex.value].confidence * 100).toFixed(1) : '0')
const currentRadius = computed(() => mockData.value[currentIndex.value]?.radius || 0)
const confidenceLevel = computed(() => {
  const conf = mockData.value[currentIndex.value]?.confidence || 0
  return `${(conf * 100).toFixed(1)}%\n(${conf >= 0.95 ? '高' : conf >= 0.85 ? '中' : '低'}可信度)`
})

interface SeriesData {
  lines: Array<{
    coords: [number[], number[]]
    effect: {
      color: string
    }
  }>
  points: PredictPoint[]
  areas: Array<{
    center: number[]
    radius: number
  }>
}

const generateSeriesData = (index: number): SeriesData => {
  return {
    lines: Array.from({ length: index }, (_, i) => ({
      coords: [
        [mockData.value[i].value[0], mockData.value[i].value[1]],
        [mockData.value[i + 1].value[0], mockData.value[i + 1].value[1]]
      ],
      effect: {
        color: `rgba(255,${150 - i * 10},${150 - i * 10},0.8)`
      }
    })),
    points: mockData.value.slice(0, index + 1),
    areas: mockData.value.slice(0, index + 1).map(point => ({
      center: [point.value[0], point.value[1]],
      radius: point.radius
    }))
  }
}

const playPause = () => {
  if (mockData.value.length === 0) {
    alert('请先填写数据并获取预测结果')
    return
  }
  isPlaying.value = !isPlaying.value
  if (isPlaying.value) {
    intervalId = window.setInterval(() => {
      if (currentIndex.value < mockData.value.length - 1) {
        currentIndex.value++
        chartInstance?.dispatchAction({
          type: 'timelineChange',
          currentIndex: currentIndex.value
        })
      } else {
        isPlaying.value = false
        if (intervalId) {
          clearInterval(intervalId)
        }
      }
    }, 1500)
  } else if (intervalId) {
    clearInterval(intervalId)
  }
}

const toggleRoam = () => {
  isRoamEnabled.value = !isRoamEnabled.value
  if (chartInstance) {
    chartInstance.setOption({
      geo: {
        roam: isRoamEnabled.value
      }
    })
  }
}

const initChart = () => {
  if (!chartRef.value) return

  chartInstance = echarts.init(chartRef.value)

  const baseOption: ECOption = {
    backgroundColor: 'transparent',
    title: {
      text: '失踪人口轨迹预测系统',
      subtext: '数据来源：人口信息数据库',
      textStyle: {
        color: '#f5222d',
        fontSize: 24
      },
      left: 'center'
    },
    geo: {
      map: 'china',
      roam: isRoamEnabled.value,
      itemStyle: {
        areaColor: '#fff1f0',
        borderColor: '#444'
      },
      label: {
        show: true,
        color: '#ff7875'
      },
      zoom: 1.1
    },
    visualMap: {
      type: 'continuous',
      dimension: 2,
      min: 0,
      max: 20,
      calculable: true,
      inRange: {
        color: [colorPalette.mainRed, colorPalette.secondaryRed]
      },
      textStyle: {
        color: colorPalette.textPrimary
      }
    },
    tooltip: {
      trigger: 'item',
      backgroundColor: 'rgba(40,40,40,0.9)',
      borderColor: colorPalette.mainRed,
      textStyle: {
        color: 'white'
      },
      formatter: (params: any) => {
        const data = params.data as PredictPoint
        return `
          <div class="tooltip-content">
            <h4>${data.name}</h4>
            <p>🕒 ${data.time}</p>
            <p>📈 概率：${data.confidence * 100}%</p>
            <p>📍 坐标：${data.value[0].toFixed(4)}, ${data.value[1].toFixed(4)}</p>
            <p>📏 半径：${data.radius}公里</p>
          </div>
        `
      }
    }
  }

  const option: ECOption = {
    baseOption: baseOption,
    options: [{
      series: []
    }]
  }

  chartInstance.setOption(option)

  chartInstance.on('click', 'series.scatter', (params: any) => {
    console.log('点击预测点:', params.data)
  })
}

const resizeChart = () => chartInstance?.resize()

onMounted(() => {
  initChart()
  window.addEventListener('resize', resizeChart)
})

onUnmounted(() => {
  window.removeEventListener('resize', resizeChart)
  chartInstance?.dispose()
  if (intervalId) clearInterval(intervalId)
})

watch(currentIndex, (newVal) => {
  chartInstance?.dispatchAction({
    type: 'timelineChange',
    currentIndex: newVal
  })
})

// 定义图表选项类型
type ECOption = ComposeOption<
  TimelineComponentOption | ScatterSeriesOption | LinesSeriesOption | GeoComponentOption
>

// 修改提交表单的方法
const submitForm = async () => {
  try {
    const response = await trajectoryRequest.get<ApiResponse>('/predict', {
      params: {
        start_lat: formData.value.start_lat,
        start_lon: formData.value.start_lon,
        age: formData.value.age,
        gender: formData.value.gender,
        height: formData.value.height,
        weight: formData.value.weight,
        transport_mode: formData.value.transport_mode
      }
    })

    // 计算半径的最大值和最小值
    const maxRadius = Math.max(...response.data.predictions.map(p => p.search_radius_km))
    const minRadius = Math.min(...response.data.predictions.map(p => p.search_radius_km))

    // 将 API 返回的数据转换为图表所需的格式，修正经纬度顺序
    const predictions: PredictPoint[] = response.data.predictions.map((pred: Prediction) => ({
      name: new Date(pred.date).toLocaleDateString(),
      value: [pred.mean_coordinates[1], pred.mean_coordinates[0], pred.search_radius_km] as [number, number, number],
      time: pred.date,
      radius: pred.search_radius_km,
      confidence: pred.probability / 100
    }))

    mockData.value = predictions
    showInputForm.value = false

    // 重置图表
    if (chartInstance) {
      currentIndex.value = 0
      const timelineData = predictions.map(d => d.time)

      const baseOption: ECOption = {
        backgroundColor: 'transparent',
        title: {
          text: '失踪人口轨迹预测系统',
          subtext: '数据来源：人口信息数据库',
          textStyle: {
            color: '#f5222d',
            fontSize: 24
          },
          left: 'center'
        },
        geo: {
          map: 'china',
          roam: isRoamEnabled.value,
          itemStyle: {
            areaColor: '#fff1f0',
            borderColor: '#444'
          },
          label: {
            show: true,
            color: '#ff7875'
          },
        },
        visualMap: {
          type: 'continuous',
          dimension: 2,
          min: minRadius, // 使用实际最小半径
          max: maxRadius, // 使用实际最大半径
          calculable: true,
          inRange: {
            color: [colorPalette.mainRed, colorPalette.secondaryRed]
          },
          textStyle: {
            color: colorPalette.textPrimary
          }
        },
        tooltip: {
          trigger: 'item',
          backgroundColor: 'rgba(40,40,40,0.9)',
          borderColor: colorPalette.mainRed,
          textStyle: {
            color: 'white'
          },
          formatter: (params: any) => {
            const data = params.data as PredictPoint
            return `
              <div class="tooltip-content">
                <h4>${data.name}</h4>
                <p>🕒 ${data.time}</p>
                <p>📈 概率：${data.confidence * 100}%</p>
                <p>📍 坐标：${data.value[0].toFixed(4)}, ${data.value[1].toFixed(4)}</p>
                <p>📏 半径：${data.radius}公里</p>
              </div>
            `
          }
        }
      }

      const options = predictions.map((_, index) => {
        const seriesData = generateSeriesData(index)
        return {
          series: [
            {
              type: 'lines' as const,
              coordinateSystem: 'geo',
              effect: {
                show: true,
                period: 4,
                trailLength: 0.1,
                symbol: 'arrow',
                symbolSize: 8
              },
              lineStyle: {
                color: colorPalette.mainRed,
                width: 1.5,
                opacity: 0.8
              },
              data: seriesData.lines
            },
            {
              type: 'scatter' as const,
              coordinateSystem: 'geo',
              symbolSize: (val: number[]) => val[2] / 10,
              itemStyle: {
                shadowBlur: 20,
                shadowColor: 'rgba(255,50,50,0.5)'
              },
              data: seriesData.points
            }
          ]
        }
      })

      const option: ECOption = {
        baseOption: baseOption,
        timeline: {
          axisType: 'time',
          currentIndex: currentIndex.value,
          data: timelineData,
          label: {
            color: colorPalette.textPrimary
          },
          progress: {
            lineStyle: {
              color: colorPalette.mainRed
            }
          },
          controlStyle: {
            color: colorPalette.mainRed,
            borderColor: colorPalette.mainRed
          }
        },
        options: options
      }

      chartInstance.setOption(option)

      // 添加时间轴变化事件监听
      chartInstance.on('timelinechanged', (e: any) => {
        currentIndex.value = e.currentIndex
      })
    }
  } catch (error) {
    alert('预测请求失败，请检查输入参数是否正确')
  }
}
</script>

<style scoped>
/* 保持样式不变 */
.chart-container {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  min-height: 400px; /* 添加最小高度 */
}

.chart {
  width: 100%;
  height: 100%;
  min-height: 400px; /* 添加最小高度 */
}

.control-panel {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 100;
  padding: 15px;
  border-radius: 8px;
  border: 1px solid;
  backdrop-filter: blur(5px);
  width: 280px;
}

.time-control button {
  background: #f54c4d;
  border: none;
  padding: 8px 15px;
  border-radius: 4px;
  color: white;
  cursor: pointer;
  margin-right: 10px;
}

.time-control input[type="range"] {
  width: 100%;
  margin-top: 10px;
  accent-color: #ff4d4d;
}

.legend-item {
  display: flex;
  align-items: center;
  margin: 8px 0;
}

.dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin-right: 8px;
}

.data-panel {
  position: absolute;
  bottom: 20px;
  right: 20px;
  padding: 15px;
  border-radius: 8px;
  border: 1px solid;
  backdrop-filter: blur(5px);
  width: 280px;
}

.panel-title {
  color: #ff4d4d;
  margin: 0 0 10px 0;
}

.data-item {
  margin: 8px 0;
  white-space: pre-line;
}

.data-item label {
  margin-right: 8px;
}

.right-controls {
  position: absolute;
  top: 20px;
  right: 20px;
  display: flex;
  gap: 10px;
  z-index: 100;
}

.input-form-button,
.roam-control-button {
  background: #f54c4d;
  border: none;
  padding: 8px 15px;
  border-radius: 4px;
  color: white;
  cursor: pointer;
}

.input-form-button:hover,
.roam-control-button:hover {
  background: #ff7875;
}

.input-form-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.input-form {
  background: white;
  padding: 20px;
  border-radius: 8px;
  width: 400px;
  max-width: 90%;
}

.input-form h3 {
  margin: 0 0 20px 0;
  color: #f54c4d;
}

.form-group {
  margin-bottom: 15px;
}

.form-group label {
  display: block;
  margin-bottom: 5px;
  color: #333;
}

.form-group input,
.form-group select {
  width: 100%;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.form-buttons {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}

.submit-button,
.cancel-button {
  padding: 8px 15px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.submit-button {
  background: #f54c4d;
  color: white;
}

.cancel-button {
  background: #f5f5f5;
  color: #333;
}

/* 小屏幕适配 */
@media (max-width: 1280px) {
  .control-panel {
    width: 160px;
    padding: 8px;
    font-size: 12px;
    top: 10px;
    left: 10px;
  }

  .data-panel {
    width: 160px;
    padding: 8px;
    font-size: 12px;
    bottom: 10px;
    right: 10px;
  }

  .time-control button {
    padding: 4px 8px;
    font-size: 12px;
    margin-right: 5px;
  }

  .time-control input[type="range"] {
    margin-top: 5px;
  }

  .legend-item {
    margin: 4px 0;
  }

  .dot {
    width: 8px;
    height: 8px;
    margin-right: 5px;
  }

  .data-item {
    margin: 4px 0;
  }

  .data-item label {
    margin-right: 5px;
  }

  .right-controls {
    top: 10px;
    right: 10px;
    gap: 5px;
  }

  .input-form-button,
  .roam-control-button {
    padding: 4px 8px;
    font-size: 12px;
  }
}
</style>
